package common;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class StringUtils
{
	public static final String BLANK = "";
	public static final String COMMA = ",";
	public static final String SPACE = " ";

	public static String[] copy(String[] source)
	{
		if (source == null)
		{
			return null;
		}
		int length = source.length;
		String[] result = new String[length];
		System.arraycopy(source, 0, result, 0, length);
		return result;
	}

	public static String[] merge(String[] _arr1, String[] _arr2)
	{
		if (_arr1 == null)
			return _arr2;
		if (_arr2 == null)
			return _arr1;

		int length1 = _arr1.length;
		int length2 = _arr2.length;

		if (length1 + length2 <= 0)
			return null;

		String[] newArr = new String[length1 + length2];

		if (length1 > 0)
			System.arraycopy(_arr1, 0, newArr, 0, length1);
		if (length2 > 0)
			System.arraycopy(_arr2, 0, newArr, length1, length2);

		return newArr;
	}

	public static boolean contains(String s, String text)
	{
		return contains(s, text, COMMA);
	}

	public static boolean contains(String s, String text, String delimiter)
	{
		if ((s == null) || (text == null) || (delimiter == null))
			return false;

		if (!s.endsWith(delimiter))
			s += delimiter;

		int pos = s.indexOf(delimiter + text + delimiter);

		if (pos == -1)
		{
			if (s.startsWith(text + delimiter))
				return true;
			else
				return false;
		}
		else
			return true;
	}

	public static int count(String s, String text)
	{
		if ((s == null) || (text == null))
			return 0;

		int count = 0;

		int pos = s.indexOf(text);

		while (pos != -1)
		{
			pos = s.indexOf(text, pos + text.length());
			count++;
		}

		return count;
	}

	public static boolean endsWith(String s, char end)
	{
		return startsWith(s, (new Character(end)).toString());
	}

	public static boolean endsWith(String s, String end)
	{
		if ((s == null) || (end == null))
			return false;

		if (end.length() > s.length())
			return false;

		String temp = s.substring(s.length() - end.length(), s.length());

		if (temp.equalsIgnoreCase(end))
			return true;
		else
			return false;
	}

	public static String merge(Collection<?> list)
	{
		return merge(list, COMMA);
	}

	public static String merge(Collection<?> list, String delimiter)
	{
		return merge((String[]) list.toArray(new String[list.size()]),
				delimiter);
	}

	public static String merge(String array[])
	{
		return merge(array, COMMA);
	}

	public static String merge(String array[], String delimiter)
	{
		if (array == null)
		{
			return null;
		}

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < array.length; i++)
		{
			sb.append(array[i].trim());

			if ((i + 1) != array.length)
			{
				sb.append(delimiter);
			}
		}

		return sb.toString();
	}

	public static String remove(String s, String remove)
	{
		return remove(s, remove, COMMA);
	}

	public static String remove(String s, String remove, String delimiter)
	{
		if ((s == null) || (remove == null) || (delimiter == null))
			return null;

		if (!s.endsWith(delimiter))
			s += delimiter;

		while (contains(s, remove, delimiter))
		{
			int pos = s.indexOf(delimiter + remove + delimiter);

			if (pos == -1)
			{
				if (s.startsWith(remove + delimiter))
				{
					s = s.substring(remove.length() + delimiter.length(), s
							.length());
				}
			}
			else
			{
				s = s.substring(0, pos)
						+ s.substring(pos + remove.length()
								+ delimiter.length(), s.length());
			}
		}

		return s;
	}

	public static String delete(String s, char[] chs)
	{
		if (chs == null || chs.length <= 0)
			return s;
		StringBuffer buffer = new StringBuffer(s);
		for (int i = buffer.length() - 1; i >= 0; i--)
		{
			char ch = buffer.charAt(i);
			for (int j = 0; j < chs.length; j++)
			{
				if (ch == chs[j])
					buffer.deleteCharAt(i);
			}
		}

		return buffer.toString();
	}

	public static String replace(String s, char oldSub, char newSub)
	{
		return replace(s, oldSub, new Character(newSub).toString());
	}

	public static String replace(String s, char oldSub, String newSub)
	{
		if ((s == null) || (newSub == null))
		{
			return null;
		}

		char[] c = s.toCharArray();

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < c.length; i++)
		{
			if (c[i] == oldSub)
			{
				sb.append(newSub);
			}
			else
			{
				sb.append(c[i]);
			}
		}

		return sb.toString();
	}

	public static String replace(String s, String oldSub, String newSub)
	{
		if ((s == null) || (oldSub == null) || (newSub == null))
		{
			return null;
		}

		int y = s.indexOf(oldSub);

		if (y >= 0)
		{
			StringBuffer sb = new StringBuffer();

			int length = oldSub.length();
			int x = 0;

			while (x <= y)
			{
				sb.append(s.substring(x, y));
				sb.append(newSub);
				x = y + length;
				y = s.indexOf(oldSub, x);
			}

			sb.append(s.substring(x));

			return sb.toString();
		}
		else
		{
			return s;
		}
	}

	public static String replace(String s, String[] oldSubs, String[] newSubs)
	{
		if ((s == null) || (oldSubs == null) || (newSubs == null))
		{
			return null;
		}

		if (oldSubs.length != newSubs.length)
		{
			return s;
		}

		for (int i = 0; i < oldSubs.length; i++)
		{
			s = replace(s, oldSubs[i], newSubs[i]);
		}

		return s;
	}

	public static String replace(String s, char[] oldChars, String[] newSubs)
	{
		if ((s == null) || (oldChars == null) || (newSubs == null))
		{
			return null;
		}

		if (oldChars.length != newSubs.length)
		{
			return s;
		}

		for (int i = 0; i < oldChars.length; i++)
		{
			s = replace(s, oldChars[i], newSubs[i]);
		}

		return s;
	}

	public static String reverse(String s)
	{
		if (s == null)
		{
			return null;
		}

		char[] c = s.toCharArray();
		char[] reverse = new char[c.length];

		for (int i = 0; i < c.length; i++)
		{
			reverse[i] = c[c.length - i - 1];
		}

		return new String(reverse);
	}

	public static String shorten(String s)
	{
		return shorten(s, 20);
	}

	public static String shorten(String s, int length)
	{
		return shorten(s, length, "..");
	}

	public static String shorten(String s, String suffix)
	{
		return shorten(s, 20, suffix);
	}

	public static String shorten(String s, int length, String suffix)
	{
		if (s == null || suffix == null)
		{
			return null;
		}

		if (s.length() > length)
		{
			s = s.substring(0, length) + suffix;
		}

		return s;
	}

	public static Set<String> splitAsSet(String s, String delimiter)
	{
		Set<String> collections = new HashSet<String>() ;
		if (s == null || s.length() <= 0)
			return collections;

		if (delimiter == null || delimiter.length() <= 0)
		{
			collections.add( s ) ;
			return collections ;
		}
		
		if (!s.endsWith(delimiter))
			s += delimiter;

		if (s.equals(delimiter))
		{
			collections.add( "" ) ;
			return collections ;
		}

		if (delimiter.equals("\n") || delimiter.equals("\r"))
		{
			try
			{
				BufferedReader br = new BufferedReader(new StringReader(s));
				String line = null;
				while ((line = br.readLine()) != null)
					collections.add(line);
				br.close();
			}
			catch (IOException ioe)
			{
				ioe.printStackTrace();
			}
		}
		else
		{
			int offset = 0;
			int pos = s.indexOf(delimiter, offset);

			while (pos != -1)
			{
				collections.add(s.substring(offset, pos));
				offset = pos + delimiter.length();
				pos = s.indexOf(delimiter, offset);
			}
		}

		return collections;
	}

	public static String[] split(String s)
	{
		return split(s, COMMA);
	}

	public static String[] split(String s, String delimiter)
	{
		if (s == null || s.length() <= 0)
			return new String[0];

		if (delimiter == null || delimiter.length() <= 0)
			return new String[] { s };

		if (!s.endsWith(delimiter))
			s += delimiter;

		if (s.equals(delimiter))
			return new String[] { "" };

		List<String> nodeValues = new ArrayList<String>();

		if (delimiter.equals("\n") || delimiter.equals("\r"))
		{
			try
			{
				BufferedReader br = new BufferedReader(new StringReader(s));

				String line = null;

				while ((line = br.readLine()) != null)
				{
					nodeValues.add(line);
				}

				br.close();
			}
			catch (IOException ioe)
			{
				ioe.printStackTrace();
			}
		}
		else
		{
			int offset = 0;
			int pos = s.indexOf(delimiter, offset);

			while (pos != -1)
			{
				nodeValues.add(s.substring(offset, pos));

				offset = pos + delimiter.length();
				pos = s.indexOf(delimiter, offset);
			}
		}

		return (String[]) nodeValues.toArray(new String[0]);
	}

	public static String[] split(String s, String delimiter, int num )
	{
		if (s == null || s.length() <= 0 ||  num == 0 )
			return new String[0];

		String[] fields = new String[num] ;
		int offset = 0 ;
		int pos = 0 ;
		int idx = 0 ;
		int len = delimiter.length() ;

		while( true )
		{
			pos = s.indexOf(delimiter, offset) ;
			if( pos < 0 )
			{
				if( offset < s.length() )
					fields[idx++] = s.substring(offset) ;
				break ;
			}
			
			fields[idx++] = s.substring(offset, pos) ;
			offset = pos + len ;
			if( idx == num-1 )
			{
				if( s.endsWith(delimiter) )
					fields[idx] = s.substring(offset,s.length()-len) ;
				else
					fields[idx] = s.substring(offset) ;
				break ;
			}
			pos = s.indexOf(delimiter, offset) ;
		}
		return fields ;
	}

	public static String[] split(String s, char ch, int num )
	{
		if (s == null || s.length() <= 0 ||  num == 0 )
			return new String[0];

		String[] fields = new String[num] ;
		int offset = 0 ;
		int pos = 0 ;
		int idx = 0 ;
		int len = 1 ;

		while( true )
		{
			pos = s.indexOf(ch, offset) ;
			if( pos < 0 )
			{
				if( offset < s.length() )
					fields[idx++] = s.substring(offset) ;
				break ;
			}
			
			fields[idx++] = s.substring(offset, pos) ;
			offset = pos + len ;
			if( idx == num-1 )
			{
				if( s.charAt(s.length()-1) == ch )
					fields[idx] = s.substring(offset,s.length()-1) ;
				else
					fields[idx] = s.substring(offset) ;
				break ;
			}
			pos = s.indexOf(ch, offset) ;
		}
		return fields ;
	}

	public static String[] token(String _src, String _start, String _end)
	{
		if (_src == null || _start == null || _end == null
				|| _src.length() <= 0 || _start.length() <= 0
				|| _end.length() <= 0)
			return null;

		String src = _src;
		if (_start.equals(_end))
		{
			if (!src.endsWith(_end))
				src += _end;
			if (!src.startsWith(_start))
				src = _start + src;
		}

		int start = 0;
		int end = 0;
		int startLength = _start.length();
		List<String> tokenList = new ArrayList<String>();

		while (true)
		{
			start = src.indexOf(_start, start);
			if (start < 0)
				break;
			start = start + startLength;
			end = src.indexOf(_end, start);
			if (end < 0)
				break;
			else
				tokenList.add(src.substring(start, end));

			start = end;
		}

		if (tokenList.size() <= 0)
			return null;
		else
		{
			String[] tokenArr = new String[tokenList.size()];
			tokenList.toArray(tokenArr);
			return tokenArr;
		}
	}

	public static String between(String _src, String _split, String _end)
	{
		return between(_src, _split, _end, 0);
	}

	public static String between(String _src, String _start, String _end,
			int _no)
	{
		if (_src == null || _start == null || _end == null
				|| _src.length() <= 0 || _start.length() <= 0
				|| _end.length() <= 0)
			return null;
		if (_no < 0)
			_no = 0;

		String src = _src;

		int count = -1;
		int start = 0;
		int end = 0;
		int startLength = _start.length();

		while (true)
		{
			start = src.indexOf(_start, start);
			if (start < 0)
				return null;
			start = start + startLength;
			end = src.indexOf(_end, start);
			if (end < 0)
				return null;
			if (++count == _no)
				return src.substring(start, end);

			start = end;
		}
	}

	public static String before(String _src, String _split)
	{
		return before(_src, _split, 0);
	}

	public static String before(String _src, String _split, int _no)
	{
		if (_src == null || _split == null || _src.length() <= 0
				|| _split.length() <= 0)
			return null;
		if (_no < 0)
			_no = 0;

		int count = -1;
		int start = 0;
		int index = 0;
		int length = _split.length();

		while ((index = _src.indexOf(_split, start)) >= 0)
		{
			if (++count == _no)
				break;
			start = index + length;
		}

		if (index > 0)
			return _src.substring(0, index);
		else if (index == 0)
			return null;
		else
			return _src;
	}

	public static String after(String _src, String _split)
	{
		return after(_src, _split, 0);
	}

	public static String after(String _src, String _split, int _no)
	{
		if (_src == null || _split == null || _src.length() <= 0
				|| _split.length() <= 0)
			return null;
		if (_no < 0)
			_no = 0;

		int count = -1;
		int start = 0;
		int index = 0;
		int length = _split.length();

		while ((index = _src.indexOf(_split, start)) >= 0)
		{
			if (++count == _no)
				break;
			start = index + length;
		}

		if (index >= 0)
			return _src.substring(index + length);
		else
			return null;
	}

	public static boolean startsWith(String s, char begin)
	{
		return startsWith(s, (new Character(begin)).toString());
	}

	public static boolean startsWith(String s, String start)
	{
		if ((s == null) || (start == null))
		{
			return false;
		}

		if (start.length() > s.length())
		{
			return false;
		}

		String temp = s.substring(0, start.length());

		if (temp.equalsIgnoreCase(start))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	public static String trimLeading(String s)
	{
		for (int i = 0; i < s.length(); i++)
		{
			if (!Character.isWhitespace(s.charAt(i)))
				return s.substring(i, s.length());
		}

		return BLANK;
	}

	public static String trimTrailing(String s)
	{
		for (int i = s.length() - 1; i >= 0; i--)
		{
			if (!Character.isWhitespace(s.charAt(i)))
				return s.substring(0, i + 1);
		}

		return BLANK;
	}

	public static String trim(String s,char ch)
	{
		return trimTrailing( trimLeading(s, ch), ch) ;
	}
	
	public static String trimLeading(String s,char ch)
	{
		for (int i = 0; i < s.length(); i++)
		{
			if (ch!=s.charAt(i))
				return s.substring(i, s.length());
		}

		return BLANK;
	}

	public static String trimTrailing(String s,char ch)
	{
		for (int i = s.length() - 1; i >= 0; i--)
		{
			if (ch!=s.charAt(i))
				return s.substring(0, i + 1);
		}

		return BLANK;
	}

	public static String wrap(String text)
	{
		return wrap(text, 80, "\n");
	}

	public static String wrap(String text, int width, String lineSeparator)
	{
		if (text == null)
		{
			return null;
		}

		StringBuffer sb = new StringBuffer();

		try
		{
			BufferedReader br = new BufferedReader(new StringReader(text));

			String s = BLANK;

			while ((s = br.readLine()) != null)
			{
				if (s.length() == 0)
				{
					sb.append(lineSeparator);
				}
				else
				{
					String[] tokens = s.split(SPACE);
					boolean firstWord = true;
					int curLineLength = 0;

					for (int i = 0; i < tokens.length; i++)
					{
						if (!firstWord)
						{
							sb.append(SPACE);
							curLineLength++;
						}

						if (firstWord)
						{
							sb.append(lineSeparator);
						}

						sb.append(tokens[i]);

						curLineLength += tokens[i].length();

						if (curLineLength >= width)
						{
							firstWord = true;
							curLineLength = 0;
						}
						else
						{
							firstWord = false;
						}
					}
				}
			}
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}

		return sb.toString();
	}

	public static String recruit(String _strSrc, int _iTotalLength,
			char _chToAdd)
	{
		return recruit(_strSrc, _iTotalLength, _chToAdd, false);
	}

	public static String recruit(String _strSrc, int _iTotalLength,
			char _chToAdd, boolean append)
	{
		int iLength = 0;
		int iTemp = 0;

		iLength = _strSrc.length();
		iTemp = _iTotalLength - iLength;
		if (iTemp <= 0)
			return _strSrc;

		char[] szTemp = new char[iTemp];

		for (int i = 0; i < iTemp; i++)
			szTemp[i] = _chToAdd;
		if (append)
			return _strSrc + String.valueOf(szTemp);
		else
			return String.valueOf(szTemp) + _strSrc;
	}

	public static String byte2hex(byte[] _buffer)
	{
		String strHex = "";
		String strTemp = "";
		for (int i = 0; i < _buffer.length; i++)
		{
			strTemp = (java.lang.Integer.toHexString(_buffer[i] & 0XFF));
			if (strTemp.length() == 1)
				strHex = strHex + "0" + strTemp;
			else
				strHex = strHex + strTemp;
			if (i < _buffer.length - 1)
				strHex = strHex + ":";
		}
		return strHex.toUpperCase();
	}

	public static String encode(byte[] _bytes, String _encoding)
	{
		try
		{
			return new String(_bytes, _encoding);
		}
		catch (UnsupportedEncodingException err)
		{
			throw new IllegalArgumentException(err);
		}
	}
	
	public static byte[] getBytes( String _src, String _encoding )
	{
		try
		{
			return _src==null?null:_encoding==null?_src.getBytes():_src.getBytes(_encoding) ;
		}
		catch (UnsupportedEncodingException err)
		{
			throw new IllegalArgumentException( err ) ;
		}
	}

	public static String[] splitByMaxChars(String _src, int _maxChars)
	{
		if (_src == null || _src.length() <= 0)
			return null;
		try
		{
			int count = _src.length() / _maxChars;
			if (_src.length() % _maxChars > 0)
				count++;

			String[] temps = new String[count];
			for (int i = 0; i < count; i++)
			{
				if (i == count - 1)
					temps[i] = _src.substring(_maxChars * i);
				else
					temps[i] = _src.substring(_maxChars * i, _maxChars * i
							+ _maxChars);
			}

			return temps;
		}
		catch (Throwable err)
		{
			throw new RuntimeException(err);
		}
	}

	public static String[] splitByMaxBytes(String _src, int _maxBytes)
	{
		if (_src == null || _src.length() <= 0)
			return null;

		try
		{
			List<String> tempList = new ArrayList<String>();
			int bytesCount = 0;
			int startPos = 0;

			for (int i = 0; i < _src.length(); i++)
			{
				int temp = _src.charAt(i);
				if (temp <= 0xFF)
					bytesCount++;
				else if (temp <= 0xFFFF)
					bytesCount += 2;
				else if (temp <= 0xFFFFFF)
					bytesCount += 3;
				else if (temp <= 0xFFFFFFFF)
					bytesCount += 4;

				if (bytesCount > _maxBytes)
				{
					tempList.add(_src.substring(startPos, i));
					startPos = i;
					bytesCount = bytesCount - _maxBytes;
				}
			}

			if (startPos < _src.length() - 1)
				tempList.add(_src.substring(startPos));

			if (tempList.size() <= 0)
				return null;

			String[] result = new String[tempList.size()];
			return (String[]) tempList.toArray(result);
		}
		catch (Throwable err)
		{
			throw new RuntimeException(err);
		}
	}

	public static String quote(String str)
	{
		return (str != null ? "'" + str + "'" : null);
	}

	public static Object quoteIfString(Object obj)
	{
		return (obj instanceof String ? quote((String) obj) : obj);
	}

	public static String encode(byte[] b, int offset, int length, String charset)
	{
		try
		{
			return new String(b, offset, length, charset);
		}
		catch (UnsupportedEncodingException err)
		{
			throw new IllegalArgumentException(err);
		}
	}

	public static void append(StringBuilder buf, String s, int offset,
			int length)
	{
		synchronized (buf)
		{
			int end = offset + length;
			for (int i = offset; i < end; ++i)
			{
				if (i >= s.length())
					break;
				buf.append(s.charAt(i));
			}
		}
	}

	public static void append(StringBuilder buf, byte b, int base)
	{
		int bi = 0xFF & b;
		int c = 48 + bi / base % base;
		if (c > 57)
			c = 97 + c - 48 - 10;
		buf.append((char) c);
		c = 48 + bi % base;
		if (c > 57)
			c = 97 + c - 48 - 10;
		buf.append((char) c);
	}
	
	
	 /* ------------------------------------------------------------ */
    /**
     * Test if a string is null or only has whitespace characters in it.
     * <p>
     * Note: uses codepoint version of {@link Character#isWhitespace(int)} to support Unicode better.
     * 
     * <pre>
     *   isBlank(null)   == true
     *   isBlank("")     == true
     *   isBlank("\r\n") == true
     *   isBlank("\t")   == true
     *   isBlank("   ")  == true
     *   isBlank("a")    == false
     *   isBlank(".")    == false
     *   isBlank(";\n")  == false
     * </pre>
     * 
     * @param str
     *            the string to test.
     * @return true if string is null or only whitespace characters, false if non-whitespace characters encountered.
     */
    public static boolean isBlank(String str)
    {
        if (str == null)
        {
            return true;
        }
        int len = str.length();
        for (int i = 0; i < len; i++)
        {
            if (!Character.isWhitespace(str.codePointAt(i)))
            {
                // found a non-whitespace, we can stop searching  now
                return false;
            }
        }
        // only whitespace
        return true;
    }
    
    /* ------------------------------------------------------------ */
    /**
     * Test if a string is not null and contains at least 1 non-whitespace characters in it.
     * <p>
     * Note: uses codepoint version of {@link Character#isWhitespace(int)} to support Unicode better.
     * 
     * <pre>
     *   isNotBlank(null)   == false
     *   isNotBlank("")     == false
     *   isNotBlank("\r\n") == false
     *   isNotBlank("\t")   == false
     *   isNotBlank("   ")  == false
     *   isNotBlank("a")    == true
     *   isNotBlank(".")    == true
     *   isNotBlank(";\n")  == true
     * </pre>
     * 
     * @param str
     *            the string to test.
     * @return true if string is not null and has at least 1 non-whitespace character, false if null or all-whitespace characters.
     */
    public static boolean isNotBlank(String str)
    {
        if (str == null)
        {
            return false;
        }
        int len = str.length();
        for (int i = 0; i < len; i++)
        {
            if (!Character.isWhitespace(str.codePointAt(i)))
            {
                // found a non-whitespace, we can stop searching  now
                return true;
            }
        }
        // only whitespace
        return false;
    }
    
    
    public static String toLowerCaseFirstOne(String s)
    {
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }
    public static String toUpperCaseFirstOne(String s)
    {
        if(Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }
    
    public static List<String> toListStr(String values, String separator) {
		if (StringUtils.isBlank(values))
			return null;
		String[] arr = StringUtils.split(values, separator);
		List<String> results = new ArrayList<String>(arr.length);
		for (String str : arr) {
			results.add(str);
		}
		return results;
	}
}

